/**
* @file gui_core.h
* @brief gui core
* @details 
* @author huangbin
* @version V1.0.0
* @date 2025-06-12
* @copyright All documents are copyrighted by Shenzhen Xinlongwei Technology Co., LTD.
*            They may not be used for commercial purposes without permission
*/

#ifndef __GUI_CORE_H__
#define __GUI_CORE_H__

/*============================ INCLUDES ======================================*/


#include "arm_2d_helper.h"
#include "arm_2d_disp_adapters.h"

#include "gui_message.h"


#ifdef   __cplusplus
extern "C" {
#endif

#if defined(__clang__)
#   pragma clang diagnostic push
#   pragma clang diagnostic ignored "-Wmissing-declarations"
#   pragma clang diagnostic ignored "-Wmicrosoft-anon-tag"
#   pragma clang diagnostic ignored "-Wpadded"
#endif

/*============================ MACROS ========================================*/

/* OOC header, please DO NOT modify  */
#ifdef __GUI_CORE_IMPLEMENT__
#   undef   __GUI_CORE_IMPLEMENT__
#   define  __ARM_2D_IMPL__
#elif defined(__XM_GUI_INHERIT__)
#   undef   __XM_GUI_INHERIT__
#   define __ARM_2D_INHERIT__
#endif
#include "arm_2d_utils.h"

/*============================ MACROS ========================================*/
/*============================ MACROFIED FUNCTIONS ===========================*/

#define RG_PROCESS_MSG(__GUI_PTR, __ITEM_NAME)                                  \
        arm_using(bool bIsMessageHandled = false)                               \
            for(gui_msg_core_t *__ITEM_NAME = gui_msg_handling_begin(__GUI_PTR); \
                (__ITEM_NAME != NULL);                                          \
                ({                                                              \
                    gui_msg_handling_end((__GUI_PTR), bIsMessageHandled);        \
                    bIsMessageHandled = false;                                  \
                    __ITEM_NAME = gui_msg_handling_begin(__GUI_PTR);             \
                }))

/*============================ TYPES =========================================*/

typedef struct xm_gui_t xm_gui_t;


typedef struct xm_gui_on_msg_evt_t xm_gui_on_msg_evt_t;

typedef bool gui_msg_handler_t(  xm_gui_t *ptGUI, 
                                void  *pTarget, 
                                gui_msg_core_t *ptMSG);

struct xm_gui_on_msg_evt_t {
    xm_gui_on_msg_evt_t    *ptNext;

    gui_msg_handler_t        *fnHandler;
    void                    *pTarget;
} ;



typedef struct xm_gui_cfg_t {
    arm_2d_scene_player_t *ptDispAdapter;                                       /* mandatory */
    arm_fsm_rt_t (*fnDispAdapterTask)(void);                                    /* mandatory */

    struct {
        gui_msg_t       *ptItems;
        uint_fast16_t   hwCount;
    } Message;

    gui_msg_key_frontend_cfg_t      tKeyFrontend;
    gui_msg_pointer_frontend_cfg_t  tPointerFrontend;

    gui_msg_pointer_frontend_pipeline_t *ptPipelines;
    uint_fast8_t chPipelineNo;
    uint8_t bOnlyTheTopSceneCanHandleMessage    : 1;
    uint8_t                                     : 3;
    uint8_t u4MessageBatchProcessingNumber      : 4;

    /*!
     * \brief user defined message preprocessing handler
     * \note this function pointer is OPTIONAL
     * \param[in] ptThis the xm_gui_t object
     * \param[in] ptMSG the target message
     * \retval true skip the system default message handler
     * \retval false use the system default message handler
     */
    bool (*fnUserMessagePreprocessingHandler)(  xm_gui_t *ptThis, 
                                                gui_msg_core_t *ptMSG);

    /*!
     * \brief user defined default message handler
     * \note this function pointer is OPTIONAL
     * \param[in] ptThis the xm_gui_t object
     * \param[in] ptMSG the target message
     * \retval true skip the system default message handler
     * \retval false use the system default message handler
     */
    bool (*fnUserDefaultMessageHandler)(xm_gui_t *ptThis, 
                                        gui_msg_core_t *ptMSG);  

} xm_gui_cfg_t;


struct xm_gui_t {
ARM_PRIVATE(
    xm_gui_cfg_t           tCFG;

    gui_helper_msg_t        tMSGCTRL;

    struct {
        gui_msg_key_frontend_t  tKey;

        gui_msg_pointer_frontend_t tPointer;
    } MessageFrontend;

    gui_helper_msg_fifo_t   tAppMessageFIFO;

    xm_gui_on_msg_evt_t    *ptEventList;

    struct {
        uint8_t bNeedToDrawFrame            : 1;
        uint8_t bConsumeResidualMessage     : 1;
        uint8_t                             : 6;
        int64_t lTimestamp;
    } Runtime;
)
};

/*============================ GLOBAL VARIABLES ==============================*/
/*============================ PROTOTYPES ====================================*/

extern
ARM_NONNULL(1, 2)
arm_2d_err_t gui_init(xm_gui_t *ptThis, xm_gui_cfg_t *ptCFG);

extern
ARM_NONNULL(1)
arm_fsm_rt_t gui_task(xm_gui_t *ptThis, int_fast8_t chFramerate);

extern
ARM_NONNULL(1)
arm_2d_scene_player_t *gui_get_disp_adapter(xm_gui_t *ptThis);

extern
ARM_NONNULL(1)
gui_msg_key_frontend_t *gui_get_key_frontend(xm_gui_t *ptThis);

extern
ARM_NONNULL(1)
gui_msg_pointer_frontend_t *gui_get_pointer_frontend(xm_gui_t *ptThis);

extern
ARM_NONNULL(1)
gui_msg_t *gui_msg_new(xm_gui_t *ptThis);

extern
ARM_NONNULL(1,2)
void gui_send_msg(xm_gui_t *ptThis,
                 gui_msg_core_t *ptMSG);

extern
ARM_NONNULL(1)
bool gui_send_pointer_evt(xm_gui_t *ptThis, 
                         uint8_t chPointerEvent,
                         uint16_t hwPointerIndex,
                         int16_t iX,
                         int16_t iY);

extern
ARM_NONNULL(1)
bool gui_send_key_evt(   xm_gui_t *ptThis, 
                        uint8_t chKeyEvent,
                        uint16_t hwKeyValue);


extern
ARM_NONNULL(1,2)
void gui_register_msg_handler(   xm_gui_t *ptThis, 
                                xm_gui_on_msg_evt_t *ptEventHandler);

extern
ARM_NONNULL(1,2)
void gui_unregister_msg_handler( xm_gui_t *ptThis, 
                                xm_gui_on_msg_evt_t *ptEventHandler);
                                
extern
ARM_NONNULL(1)
gui_msg_core_t *gui_msg_handling_begin(xm_gui_t *ptThis);

extern
ARM_NONNULL(1)
void gui_msg_handling_end(xm_gui_t *ptThis, bool bHandled);

extern
ARM_NONNULL(1)
bool gui_send_timer_evt(   xm_gui_t *ptThis,uint8_t chIndex);
extern
ARM_NONNULL(1)
bool gui_send_communication_evt(   xm_gui_t *ptThis,uint8_t chCmdcode,uint32_t wparameter);


#if defined(__clang__)
#   pragma clang diagnostic pop
#endif

#ifdef   __cplusplus
}
#endif

#endif
